package com.websql.yousql.config.dataSource;

import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public class RoutingDataSource extends AbstractRoutingDataSource {

    /**
     * 动态数据源信息
     */
    private final ConcurrentMap<Object, Object> dynamicTargetDataSources = new ConcurrentHashMap<>();
    /**
     * 数据源创建提供者
     */
    @Resource
    private DataSourceProvider dataSourceProvider;

    @Override
    public void setTargetDataSources(Map<Object, Object> targetDataSources) {
        synchronized (this) {
            super.setTargetDataSources(targetDataSources);
            this.dynamicTargetDataSources.putAll(targetDataSources);
        }
    }

    @Override
    protected Object determineCurrentLookupKey() {
        String dataSourceKey = RoutingDataSourceContext.getDataSourceRoutingKey();
        if (!StringUtils.hasLength(dataSourceKey)) {
            //返回空，即使用默认数据源
            return null;
        }

        //检查是否存在该dataSource，不存在则创建
        this.checkAndInitDataSource(dataSourceKey);
        return dataSourceKey;
    }

    /**
     * 检查是否存在数据源，不存在则进行初始化数据源操作
     * @param botCode
     */
    private void checkAndInitDataSource(String botCode) {
        if (!dynamicTargetDataSources.containsKey(botCode)) {
            synchronized (this) {
                if (!dynamicTargetDataSources.containsKey(botCode)) {
                    DataSource dataSource = dataSourceProvider.createDataSourceByBotCode(botCode);
                    if (null != dataSource) {
                        addDataSource(botCode, dataSource);
                    }
                }
            }
        }
    }

    /**
     * 添加数据源到动态数据源中
     * @param dataSourceKey
     * @param dataSource
     * @return
     */
    private synchronized boolean addDataSource(String dataSourceKey, DataSource dataSource) {
        dynamicTargetDataSources.put(dataSourceKey, dataSource);
        // 将map赋值给父类的TargetDataSources
        setTargetDataSources(dynamicTargetDataSources);
        // 将TargetDataSources中的连接信息放入resolvedDataSources管理
        super.afterPropertiesSet();
        return true;
    }

}
